package com.jsj.subway.ai.agent.rag;

import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsj.subway.ai.agent.rag.config.KbConfig;
import com.jsj.subway.ai.agent.rag.models.KnowledgeBase;
import com.jsj.subway.ai.largemodel.models.Result;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
public class KbApiClient implements KbClient {

    @Getter
    @NotNull
    private List<String> apiKey;
    /**
     * https://dashscope.aliyuncs.com
     * 自定义api host使用builder的方式构造client
     */
    @Getter
    private String apiHost;
    /**
     * 自定义的okHttpClient
     * 如果不自定义 ，就是用sdk默认的OkHttpClient实例
     */
    @Getter
    private OkHttpClient okHttpClient;

    @Getter
    private KbApi api;



    private KbApiClient(Builder builder) {
        if (CollectionUtil.isEmpty(builder.apiKey)) {
            throw new RuntimeException("api key not nul");
        }
        apiKey = builder.apiKey;
        apiHost = builder.apiHost;

        if (Objects.isNull(builder.okHttpClient)) {
            builder.okHttpClient = this.okHttpClient();
        } else {
            //自定义的okhttpClient  需要增加api keys
            builder.okHttpClient = builder.okHttpClient
                    .newBuilder()
                    //.addInterceptor(authInterceptor)
                    .build();
        }
        okHttpClient = builder.okHttpClient;

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        this.api = new Retrofit.Builder()
                .baseUrl(apiHost)
                .client(okHttpClient)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(JacksonConverterFactory.create(objectMapper))
                .build().create(KbApi.class);
    }
    private OkHttpClient okHttpClient() {
        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                //.addInterceptor(this.authInterceptor)
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(50, TimeUnit.SECONDS)
                .readTimeout(50, TimeUnit.SECONDS)
                .build();
        return okHttpClient;
    }
    public static Builder builder() {
        return new Builder();
    }

    public static final class Builder {
        private @NotNull

        List<String> apiKey;

        private String apiHost;

        private KbConfig apiConfig;

        /**
         * 自定义OkhttpClient
         */
        private OkHttpClient okHttpClient;


        /**
         * 自定义鉴权拦截器
         */

        public Builder() {
        }

        public Builder apiKey(@NotNull List<String> val) {
            apiKey = val;
            return this;
        }


        public Builder apiHost(String val) {
            apiHost = val;
            return this;
        }


        public Builder okHttpClient(OkHttpClient val) {
            okHttpClient = val;
            return this;
        }

        public Builder apiConfig(KbConfig apiConfig) {
            this.apiConfig = apiConfig;
            return this;
        }

        public KbClient build() {
            return new KbApiClient(this);
//            AliApiClient client =  new AliApiClient(this);
//            return (AliClient) Proxy.newProxyInstance(client.getClass().getClassLoader(),client.getClass().getInterfaces(),new AliApiClientProxyHandler(client));
        }

    }


    public Result.KbBase uploadKnowledgeBaseDocs(String fileId, MultipartBody multipartBody) {
        try {
            Call<Result.KbBase> call = api.uploadKnowledgeBaseDocs(fileId, multipartBody);
            return call.execute().body();
        } catch (IOException e) {
            log.info("get response fail:{}", e.getMessage());
            return new Result.KbBase(1, e.getMessage());
        }
    }

    public Result.KbBase deleteKnowledgeBaseDoc(String kb_name, Long id){
        try{
            KnowledgeBase.DeleteDocReq req = new KnowledgeBase.DeleteDocReq();
            req.setKb_name(kb_name);
            req.setId(id);
            Call<Result.KbBase> res =  api.downloadKnowledgeBaseDoc(req);
            return res.execute().body();
        }
        catch (IOException e){
            log.info("get response fail:{}", e.getMessage());
            return new Result.KbBase();
        }
    }

    public Result.KbBase queryKbBase(KnowledgeBase.QueryReq req){
        try{
            Call<Result.KbBase> res =  api.queryKnowledgeBase(req);
            return res.execute().body();
        }
        catch (IOException e){
            log.info("get response fail:{}", e.getMessage());
            return new Result.KbBase();
        }
    }

    public Result.KbBase createKBase(KnowledgeBase.CreateReq req){
        try{
            Call<Result.KbBase> res =  api.createkb(req);
            return res.execute().body();
        }
        catch (IOException e){
            log.info("get response fail:{}", e.getMessage());
            return new Result.KbBase();
        }
    }

    public Result.KbBase deleteKBase(KnowledgeBase.DeleteReq req){
        try{
            Call<Result.KbBase> res =  api.deletekb(req);
            return res.execute().body();
        }
        catch (IOException e){
            log.info("get response fail:{}", e.getMessage());
            return new Result.KbBase();
        }
    }
}
